﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#include "NdbClassSchema.h"
#include "NdbClassSchemaChange.h"
#include "NdbUpgradeManager.h"
#include "NdbTypeTraits.h"
#include "NdbClassSchemaLibraryOfCode.h"
#include "NdbClassIdUtils.h"

//////////////////////////////////////////////////////////////////////////

// 类声明开始
//  NS_PREFIX:  命名空间前缀，不包含最后的作用域符号::
//  CLASS_NAME: 类的名字
//  VERSION:    将要升级到的版本号。比如2表示从版本1升级到版本2。所有类的默认起始版本是1
#define BEGIN_UPGRADE_CLASS(NS_PREFIX, CLASS_NAME, VERSION) \
    class NDB##CLASS_NAME##Upgrader##VERSION \
    { \
    public: \
        NDB##CLASS_NAME##Upgrader##VERSION(); \
    }; \
    static void NDB##Upgrade##CLASS_NAME##ToVersion##VERSION(const ClassId&, NdbClassSchemaChange&); \
    static NDB##CLASS_NAME##Upgrader##VERSION _##NDB##CLASS_NAME##Upgrader##VERSION; \
    NDB##CLASS_NAME##Upgrader##VERSION::NDB##CLASS_NAME##Upgrader##VERSION() \
    { \
        ClassId classId(NS_PREFIX::CLASS_NAME::GetClassId()); \
        NdbClassSchemaChange classSchemaChange(VERSION); \
        NDB##Upgrade##CLASS_NAME##ToVersion##VERSION(classId, classSchemaChange); \
        gcmp::NdbUpgradeManager::GetInstance()->InsertClassSchemaChange(classId, classSchemaChange); \
    } \
    static void NDB##Upgrade##CLASS_NAME##ToVersion##VERSION(const ClassId & classId, NdbClassSchemaChange& classSchemaChange) \
    {

// 类声明结束
#define END_UPGRADE_CLASS }

//////////////////////////////////////////////////////////////////////////
// 下面的声明应该放在BEGIN_UPGRADE_CLASS和END_UPGRADE_CLASS之间
//////////////////////////////////////////////////////////////////////////

// 增加非对象（不是NdbObject）属性
//  TYPE:   属性的类型
//  NAME:   属性的名字
#define ADD_NON_OBJECT_PROPERTY(TYPE, NAME) \
    { \
        NdbPropertySchemaType propSchemaType = NdbPropertySchemaTypeTrait<TYPE>::PropertySchemaType; \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), ClassId(), classId, propSchemaType, sizeof(TYPE)); \
        IntOrFloatType intOrFloatType = NdbPropertySchemaTypeTrait<TYPE>::IntOrFloatType; \
        propChange.SetIntOrFloatType(intOrFloatType); \
        IntBaseType intBaseType = NdbPropertySchemaTypeTrait<TYPE>::IntBaseType; \
        propChange.SetIntBaseType(intBaseType); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加对象属性
//  TYPE:           属性的类型
//  NAME:           属性的名字
//  PROP_CLASS_ID:  属性的Class Id
#define ADD_OBJECT_PROPERTY(TYPE, NAME, PROP_CLASS_ID) \
    { \
        NdbPropertySchemaType propSchemaType = NdbPropertySchemaTypeTrait<TYPE>::PropertySchemaType; \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), ClassId(WSTRING_OF(PROP_CLASS_ID)), classId, propSchemaType, sizeof(TYPE)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加OwnerPtr属性
//  CONTENT_TYPE:   被OwnerPtr所Own的类型
//  NAME:           属性的名字
#define ADD_OWNERPTR_PROPERTY(CONTENT_TYPE, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), ClassId(), classId, NdbPropertySchemaType::OwnerPtrToNdbObject, sizeof(gcmp::OwnerPtr<CONTENT_TYPE>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加OwnerPtr IDBObject属性
//  CONTENT_TYPE:   被OwnerPtr所Own的类型
//  NAME:           属性的名字
#define ADD_OWNERPTR_IDB_PROPERTY(CONTENT_TYPE, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), ClassId(), classId, NdbPropertySchemaType::OwnerPtrToIDbObject, sizeof(gcmp::OwnerPtr<CONTENT_TYPE>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加NdbVector属性
//  CONTENT_TYPE:   NdbVector元素的类型
//  NAME:           属性的名字
#define ADD_ARR_PROPERTY(CONTENT_TYPE, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), gcmp::NdbClassIdUtils::GetClassIdOfPropertySchemaType(NdbPropertySchemaType::Vector), classId, NdbPropertySchemaType::Vector, sizeof(gcmp::NdbVector<CONTENT_TYPE>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加NdbSet属性
//  CONTENT_TYPE:   NdbSet元素的类型
//  NAME:           属性的名字
#define ADD_SET_PROPERTY(CONTENT_TYPE, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), gcmp::NdbClassIdUtils::GetClassIdOfPropertySchemaType(NdbPropertySchemaType::Set), classId, NdbPropertySchemaType::Set, sizeof(gcmp::NdbSet<CONTENT_TYPE>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加NdbSet属性
//  CONTENT_TYPE:   NdbSet元素的类型
//  COMPARER:       比较器
//  NAME:           属性的名字
#define ADD_SET_WITH_COMPARAER_PROPERTY(CONTENT_TYPE,COMPARER, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), gcmp::NdbClassIdUtils::GetClassIdOfPropertySchemaType(NdbPropertySchemaType::Set), classId, NdbPropertySchemaType::Set, sizeof(gcmp::NdbSet<CONTENT_TYPE COMMA COMPARER>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加NdbMap属性
//  KEY_TYPE:   NdbMap的键类型
//  VALUE_TYPE: NdbMap的值类型
//  NAME:       属性的名字
#define ADD_MAP_PROPERTY(KEY_TYPE, VALUE_TYPE, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), gcmp::NdbClassIdUtils::GetClassIdOfPropertySchemaType(NdbPropertySchemaType::Map), classId, NdbPropertySchemaType::Map, sizeof(gcmp::NdbMap<KEY_TYPE COMMA VALUE_TYPE>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加NdbMap属性
//  KEY_TYPE:   NdbMap的键类型
//  VALUE_TYPE: NdbMap的值类型
//  KEY_COMPARER: 键类型的比较器
//  NAME:       属性的名字
#define ADD_MAP_WITH_COMPARAER_PROPERTY(KEY_TYPE, VALUE_TYPE, KEY_COMPARER, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), gcmp::NdbClassIdUtils::GetClassIdOfPropertySchemaType(NdbPropertySchemaType::Map), classId, NdbPropertySchemaType::Map, sizeof(gcmp::NdbMap<KEY_TYPE COMMA VALUE_TYPE COMMA KEY_COMPARER>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加NdbUnorderedMap属性
//  KEY_TYPE:   NdbUnorderedMap的键类型
//  VALUE_TYPE: NdbUnorderedMap的值类型
//  NAME:       属性的名字
#define ADD_UMAP_PROPERTY(KEY_TYPE, VALUE_TYPE, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), gcmp::NdbClassIdUtils::GetClassIdOfPropertySchemaType(NdbPropertySchemaType::UnorderedMap), classId, NdbPropertySchemaType::UnorderedMap, sizeof(gcmp::NdbUnorderedMap<KEY_TYPE COMMA VALUE_TYPE>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 增加NdbUnorderedMap属性
//  KEY_TYPE:   NdbUnorderedMap的键类型
//  VALUE_TYPE: NdbUnorderedMap的值类型
//  KEY_COMPARER: 键类型的比较器
//  NAME:       属性的名字
#define ADD_UMAP_WITH_HASH_FUNC_PROPERTY(KEY_TYPE, VALUE_TYPE, HASH_FUNC, NAME) \
    { \
        NdbAddPropertyChange propChange(WSTRING_OF(NAME), gcmp::NdbClassIdUtils::GetClassIdOfPropertySchemaType(NdbPropertySchemaType::UnorderedMap), classId, NdbPropertySchemaType::UnorderedMap, sizeof(gcmp::NdbUnorderedMap<KEY_TYPE COMMA VALUE_TYPE COMMA HASH_FUNC>)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 删除属性
//  OLD_NAME:   被删除的属性的名字
#define DELETE_PROPERTY(OLD_NAME) \
    { \
        NdbDeletePropertyChange propChange(WSTRING_OF(OLD_NAME)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 重命名属性
//  OLD_NAME:   重命名之前的名字
//  NEW_NAME:   重命名之后的名字
#define RENAME_PROPERTY(OLD_NAME, NEW_NAME) \
    { \
        NdbRenamePropertyChange propChange(WSTRING_OF(OLD_NAME), WSTRING_OF(NEW_NAME)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 重定义属性类型（整型之间，浮点型之间，整型和浮点型之间）
//  OLD_TYPE:   重定义之前的类型
//  NEW_TYPE:   重定义之后的类型
#define RETYPE_BETWEEN_INTEGER_AND_FLOATING_PROPERTY(NAME, OLD_TYPE, NEW_TYPE) \
    { \
        static_assert(std::is_integral<OLD_TYPE>::value || std::is_floating_point<OLD_TYPE>::value, "When retype, the OLD_TYPE must be int or floating"); \
        static_assert(std::is_integral<NEW_TYPE>::value || std::is_floating_point<NEW_TYPE>::value, "When retype, the NEW_TYPE must be int or floating"); \
        const std::wstring& oldTypeName = gcmp::TypeDefTrait<OLD_TYPE>::RealName(L"Old type name should be predefined"); \
        const std::wstring& newTypeName = gcmp::TypeDefTrait<NEW_TYPE>::RealName(L"New type name should be predefined"); \
        NdbRetypePropertyChange propChange(WSTRING_OF(NAME), oldTypeName, sizeof(OLD_TYPE), newTypeName, sizeof(NEW_TYPE)); \
        IntOrFloatType intOrFloatType = NdbPropertySchemaTypeTrait<NEW_TYPE>::IntOrFloatType; \
        propChange.SetNewIntOrFloatType(intOrFloatType); \
        IntBaseType intBaseType = NdbPropertySchemaTypeTrait<NEW_TYPE>::IntBaseType;  \
        propChange.SetNewIntBaseType(intBaseType); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 从祖先类中移入属性
//  OLD_NAME:               移入之前的名字
//  NEW_NAME:               移入之后的名字
//  ANCESTOR_CLASS_NAME:    祖先类的名字（方便阅读用）
//  ANCESTOR_CLASS_ID:      祖先类的Class Id
#define MOVE_PROPERTY_FROM_ANCESTOR(OLD_NAME, NEW_NAME, ANCESTOR_CLASS_NAME, ANCESTOR_CLASS_ID) \
    { \
        NdbExchangePropertyWithAncestorChange propChange(CPCT_MOVE_FROM_ANCESTOR, WSTRING_OF(ANCESTOR_CLASS_NAME), ClassId(WSTRING_OF(ANCESTOR_CLASS_ID)), WSTRING_OF(OLD_NAME), WSTRING_OF(NEW_NAME)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 移入属性到祖先类中
//  OLD_NAME:               移入之前的名字
//  NEW_NAME:               移入之后的名字
//  ANCESTOR_CLASS_NAME:    祖先类的名字（方便阅读用）
//  ANCESTOR_CLASS_ID:      祖先类的Class Id
#define MOVE_PROPERTY_TO_ANCESTOR(OLD_NAME, NEW_NAME, ANCESTOR_CLASS_NAME, ANCESTOR_CLASS_ID) \
    { \
        NdbExchangePropertyWithAncestorChange propChange(CPCT_MOVE_TO_ANCESTOR, WSTRING_OF(ANCESTOR_CLASS_NAME), ClassId(WSTRING_OF(ANCESTOR_CLASS_ID)), WSTRING_OF(OLD_NAME), WSTRING_OF(NEW_NAME)); \
        classSchemaChange.AddPropertyChange(propChange); \
    }

// 改变父类
//  SRC_CLASS_NAME: 原父类的名字（方便阅读用）
//  SRC_CLASS_ID:   原父类的Class Id
//  DST_CLASS_NAME: 现父类的名字（方便阅读用）
//  DST_CLASS_ID:   现父类的Class Id
#define CHANGE_PARENT(SRC_CLASS_NAME, SRC_CLASS_ID, DST_CLASS_NAME, DST_CLASS_ID) \
    { \
        NdbParentClassChange parentClassChange(WSTRING_OF(SRC_CLASS_NAME), ClassId(WSTRING_OF(SRC_CLASS_ID)), WSTRING_OF(DST_CLASS_NAME), ClassId(WSTRING_OF(DST_CLASS_ID))); \
        classSchemaChange.AddParentClassChange(parentClassChange); \
    }

// 自定义对属性的处理开始
//  OLD_OBJECT_MEM_MODEL指向旧对象的内存模型
//  NEW_OBJECT_MEM_MODEL指向新对象的内存模型
#define BEGIN_UPGRADE_PROPERTY(customUpgraderOldObject, customUpgraderNewObject) \
    { \
        classSchemaChange.AddCustomizedUpgrader( \
        [](const NdbObjectMemoryModelGroupNode * pOldObjectMemoryModel, NdbObjectMemoryModelGroupNode * pNewObjectMemoryModel) -> bool { \
        NdbCustomUpgraderOldObject customUpgraderOldObject(pOldObjectMemoryModel); \
        NdbCustomUpgraderNewObject customUpgraderNewObject(pNewObjectMemoryModel); \

// 自定义对属性的处理结束
#define END_UPGRADE_PROPERTY \
        }); \
    }

#define SET_CLASS_SCHEMA_STATE(CLASS_NAME, CLASS_ID, CLASS_STATE)  \
    class NDB##CLASS_NAME##CHANGE##STATE \
    { \
    public: \
    NDB##CLASS_NAME##CHANGE##STATE(); \
    }; \
    static NDB##CLASS_NAME##CHANGE##STATE _##NDB##CLASS_NAME##CHANGE##STATE; \
    NDB##CLASS_NAME##CHANGE##STATE::NDB##CLASS_NAME##CHANGE##STATE() \
    { \
        gcmp::ClassId classId(WSTRING_OF(CLASS_ID)); \
        gcmp::NdbClassSchemaLibraryOfCode::GetInstance()->SetIsClassSchemaExist(classId, CLASS_STATE); \
    } \

//标记类删除
#define MARKUP_CLASS_DELETE(CLASS_NAME, CLASS_ID)  \
    class NDB##CLASS_NAME##CLASS##DELETE \
    { \
    public: \
    NDB##CLASS_NAME##CLASS##DELETE(); \
    }; \
    static NDB##CLASS_NAME##CLASS##DELETE _##NDB##CLASS_NAME##CLASS##DELETE; \
    NDB##CLASS_NAME##CLASS##DELETE::NDB##CLASS_NAME##CLASS##DELETE() \
    { \
        gcmp::ClassId classId(WSTRING_OF(CLASS_ID)); \
        gcmp::NdbClassSchemaLibraryOfCode::GetInstance()->SetIsClassSchemaExist(classId, false); \
    } \

